package org.tri.entity;

import javax.persistence.*;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
 * La clase {@code AnimalHistorico} representa un animal que fué marcado
 * como histórico ya que su relevancia en el negocio no es mucha, ya que
 * ya fué vendido y por lo tanto solo se mantiene como referencia para 
 * conocer los detalles de la venta.
 * El animal es considerado histórico cuando su {@code Venta} es marcada
 * como histórica. Sin embargo, la compra no necesariamente se considera
 * histórica, por lo que cada instancia posee una referencia a una compra
 * y una compra histórica, en la que solo una de ellas será válida y 
 * contendrá el la compra real.
 * @author kiira
 * @version 1.0, Nov 23, 2011
 */
@Entity
@Table ( name = "animal_hist" )
public class AnimalHistorico extends AbstractAnimal {

    /** Compra en la cual este animal fue adquirido. */
    private Compra compra;
    /** Compra historica en la cual este animal fue adquirido. */
    private CompraHistorica compraHistorica;
    /** Venta en la que este animal participo. */
    private VentaHistorica venta;

    /**
     * Constructor sin parámetros utilizado por hibernate.
     */
    protected AnimalHistorico() {
    }//end constructor

    /**
     * Devuelve la {@code Compra} en la cual este animal fue adquirido.
     * Es recomendable utilizar el método {@code obtenerCompraActual} ya
     * que siempre devuelve una instancia de {@code AbstractCompra}.
     * @return {@code Compra} asociada al animal o null si existe una
     * {@code CompraHistorica} asociada.
     */
    @ManyToOne ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, optional = true )
    @JoinColumn ( name = "compra" )
    @Cascade ( org.hibernate.annotations.CascadeType.SAVE_UPDATE )
    @Fetch ( FetchMode.SELECT )
    public Compra getCompra() {
        return compra;

    }//end método getCompra

    /**
     * Setea la {@code Compra} en la que se realizó la adquisición del
     * animal. Para uso exclusivo de hibernate.
     * @param compra {@code Compra} a setear.
     */
    protected void setCompra( Compra compra ) {
        this.compra = compra;

    }//end método setCompra

    /**
     * Devuelve la {@code CompraHistorica} en la cual este animal fué adquirido.
     * Es recomendable utilizar el método {@code obtenerCompraActual} ya
     * que siempre devuelve una instancia de {@code AbstractCompra}.
     * @return {@code CompraHistorica} asociada al animal o null si existe una
     * {@code Compra} asociada.
     */
    @ManyToOne ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, optional = true )
    @JoinColumn ( name = "compra_hist" )
    @Cascade ( org.hibernate.annotations.CascadeType.SAVE_UPDATE )
    @Fetch ( FetchMode.SELECT )
    public CompraHistorica getCompraHistorica() {
        return compraHistorica;

    }//end método getCompraHistorica

    /**
     * Setea la {@code CompraHistorica} en la que se realizó la adquisición del
     * animal. Para uso exclusivo de hibernate.
     * @param compra {@code CompraHistorica} a setear.
     */
    protected void setCompraHistorica( CompraHistorica compraHistorica ) {
        this.compraHistorica = compraHistorica;

    }//end método setCompraHistorica

    /**
     * {@inheritDoc}
     */
    @Override
    public AbstractCompra obtenerCompraActual() {
        getCompra();
        getCompraHistorica();

        return ( compra != null ) ? compra : compraHistorica;

    }//end método obtenerCompraActual

    /**
     * Devuelve la {@code Venta} en la cual este animal fué vendido.
     * @return {@code Venta} asociada al animal.
     */
    @ManyToOne ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, optional = true )
    @JoinColumn ( name = "venta" )
    @Cascade ( org.hibernate.annotations.CascadeType.SAVE_UPDATE )
    @Fetch ( FetchMode.SELECT )
    public VentaHistorica getVenta() {
        return venta;

    }//end método getVenta

    /**
     * Setea la {@code Venta} en la este animal fué vendido.
     * @param venta {@code Venta} a setear.
     */
    protected void setVenta( VentaHistorica venta ) {
        this.venta = venta;

    }//end método setVenta

    /**
     * {@inheritDoc}
     */
    @Override
    public AbstractVenta obtenerVentaActual() {
        return getVenta();

    }//end método obtenerVentaActual    

}//end clase AnimalHistorico

